;*******************************************************************************
;* @item     CosyOS-II Port
;* @file     port_cmx_s.s
;* @brief    CMSIS Cortex-M Core Port File
;* @author   迟凯峰
;* @version  V3.4.0
;* @date     2025.01.06
;*******************************************************************************
;* <<< Use Configuration Wizard in Context Menu >>>
;
; <e> 是否启用thumb汇编移植方案？
; <i> 启用该方案后，如果在 mcucfg_cmx.h 中，系统中断配置为 TIMn_IRQHandler + XXX_IRQHandler，
; <i> 用户另需在下方（Line 45、46）手动修改 PendSV_Handler 为 XXX_IRQHandler。
CMXPRT_THUMB			EQU		0
;
; <o> 指令集架构
; <0=> ARMv6-M <1=> ARMv7-M
CMXPRT_ISA              EQU		1
;
; <q> 是否启用DEBUG接口并同时启用任务PC监控？
SYSCFG_TASKPC_MONITOR	EQU		1
;
; <e> 是否启用PendSV_FIFO？
CMXPRT_PENDSVFIFO		EQU		1
;
; <o> PendSV_FIFO互斥访问方案
; <1=> 互斥访问指令 <2=> 互斥访问机制 <3=> 关闭总中断
;
; <i> 方案一、互斥访问指令
; <i> 该方案仅适用于Cortex-M3/M4/M7等支持互斥访问指令[LDREX/STREX]的内核，可实现全局不关总中断、零中断延迟。
;
; <i> 方案二、互斥访问机制
; <i> 该方案适用于所有ARM内核，可实现全局不关总中断、零中断延迟，但要求用户必须做到以下两点：
; <i> (1) 编译器可能需要开启对GNU/GCC的支持（Keil MDK不用）。
; <i> (2) 凡是调用了中断挂起服务_FIFO的中断函数，必须在函数外部上方声明寄存器变量r7，以通知编译器该中断函数不使用r7。
; <i> 声明示例：register void **mPendSV_FIFO_R7 __ASM("r7");
;
; <i> 方案三、关闭总中断
; <i> 该方案适用于所有ARM内核，并具有极短的、确定的关闭总中断时间（包括再次开启总中断在内，不超过10个指令周期）。
; <i> 该方案，内核关闭总中断仅发生在中断挂起服务装载器中的__LOAD段。
MCUCFG_PENDSVFIFO_MUTEX	EQU		1
; </e>
; <q> 浮点寄存器上下文自动保存
; <i> 是否启用浮点寄存器的上下文自动保存功能？
; <i> 如果启用了硬件浮点单元，并且在多个任务或中断中都要进行浮点运算，应该开启该功能；
; <i> 如果仅在特定的一个任务或中断中进行浮点运算，可以关闭该功能以提高性能。
MCUCFG_ASPEN_LSPEN		EQU		0
; </e>
;
;///////////////////////////////////////////////////////////////////////////////

				IF CMXPRT_THUMB == 1

				THUMB
				AREA    |.text|, CODE, READONLY

;///////////////////////////////////////////////////////////////////////////////

; PendSV软中断
; 如果在 mcucfg_cmx.h 中，系统中断配置为 TIMn_IRQHandler + XXX_IRQHandler，
; 需在下方手动修改 PendSV_Handler 为 XXX_IRQHandler。

PendSV_Handler	PROC	;用户手动修改 PendSV_Handler 为 XXX_IRQHandler
				EXPORT	PendSV_Handler	;用户手动修改 PendSV_Handler 为 XXX_IRQHandler

MCUCFG_CALLEE_PUSH_REG	EQU	32

				IMPORT	sPendSV_Handler
				IMPORT	s_task_current
				IMPORT	s_task_news
				PRESERVE8

				push	{lr}

				bl		sPendSV_Handler
;// ?RETURN
				IF		CMXPRT_ISA == 0
				cmp		r0, #0
				beq		__RETURN
				ELSE
				cbz		r0, __RETURN
				ENDIF

				isb
;// ?PROTECTING
				ldr		r1, =s_task_current
				subs	r0, #1
				IF		CMXPRT_ISA == 0
				cmp		r0, #0
				beq		__RESTORE
				ELSE
				cbz		r0, __RESTORE
				ENDIF

				mrs		r0, psp
;// 任务PC监控
			IF	SYSCFG_TASKPC_MONITOR == 1

				IMPORT	s_sign_taskmgr
				IMPORT	s_pc
				ldr		r3, =s_sign_taskmgr
				ldrb	r3, [r3]
				IF		CMXPRT_ISA == 0
				cmp		r3, #0
				beq		__PROTECTING
				ELSE
				cbz		r3, __PROTECTING
				ENDIF
				mov		r3, r0
				adds	r3, #24
				ldmia	r3, {r2}
				ldr		r3, =s_pc
				str		r2, [r3]

			ENDIF
;// 保护现场
__PROTECTING
			IF	MCUCFG_ASPEN_LSPEN == 1
				vstmdb	r0!, {s16-s31}
			ENDIF

			IF	CMXPRT_ISA == 0

				subs	r0, #MCUCFG_CALLEE_PUSH_REG
				ldr		r2, [r1]
				str		r0, [r2]
				stmia	r0!, {r4-r7}
				mov		r4, r8
				mov		r5, r9
				mov		r6, r10
				mov		r7, r11
				stmia	r0!, {r4-r7}

			ELSE

				stmdb	r0!, {r4-r11}
				ldr		r2, [r1]
				str		r0, [r2]

			ENDIF
;// 恢复现场
__RESTORE		ldr		r3, =s_task_news
				ldr		r3, [r3]
				str		r3, [r1]
				ldr		r0, [r3]

			IF	CMXPRT_ISA == 0

				adds	r0, #16
				ldmia	r0!, {r4-r7}
				mov		r11, r7
				mov		r10, r6
				mov		r9, r5
				mov		r8, r4
				mov		r1, r0
				subs	r1, #MCUCFG_CALLEE_PUSH_REG
				ldmia	r1!, {r4-r7}

			ELSE

				ldmia	r0!, {r4-r11}

			ENDIF

			IF	MCUCFG_ASPEN_LSPEN == 1
				vldmia	r0!, {s16-s31}
			ENDIF

				msr		psp, r0

__RETURN		pop		{pc}

				ALIGN

				ENDP

;///////////////////////////////////////////////////////////////////////////////

; 中断挂起服务装载器

				IF		CMXPRT_PENDSVFIFO == 1

mPendSV_FIFOLoader\
				PROC
				EXPORT	mPendSV_FIFOLoader

				IMPORT	mPendSV_FIFO_P0
				IMPORT	mPendSV_FIFO_P1
				IMPORT	m_sign_fifo

				ldr		r3, =m_sign_fifo
				ldrb	r3, [r3]
				IF		CMXPRT_ISA == 0
				cmp		r3, #0
				beq		__FIFO1
				ELSE
				cbz		r3, __FIFO1
				ENDIF

__FIFO0			ldr		r1, =mPendSV_FIFO_P0
				b		__LOAD

__FIFO1			ldr		r1, =mPendSV_FIFO_P1

				IF		MCUCFG_PENDSVFIFO_MUTEX == 1

__LOAD			ldrex	r2, [r1]
				adds	r2, #4
				strex	r3, r2, [r1]
				cmp		r3, #0
				bne		__LOAD

				ELIF	MCUCFG_PENDSVFIFO_MUTEX == 2

				IMPORT	mPendSV_FIFO_P2
				IMPORT	m_sign_load

__LOAD			push	{r0, r4}
				mov		r0, r7

				ldr		r3, =m_sign_load
				ldrb	r4, [r3]
				movs	r2, #1
				strb	r2, [r3]

__LOAD2			mov		r7, r1
				ldr		r2, [r7]
				adds	r2, #4
				str		r2, [r7]
				cmp		r7, r1
				bne		__LOAD2

				strb	r4, [r3]

				IF		CMXPRT_ISA == 0
				cmp		r4, #0
				beq		__RESR7
				ELSE
				cbz		r4, __RESR7
				ENDIF
				ldr		r7, =mPendSV_FIFO_P2
				b		__OVER

__RESR7			mov		r7, r0

__OVER			pop		{r0, r4}

				ELIF	MCUCFG_PENDSVFIFO_MUTEX == 3

__LOAD			mrs		r3, primask
				cpsid	i
				ldr		r2, [r1]
				adds	r2, #4
				str		r2, [r1]
				msr		primask, r3

				ENDIF

				str		r0, [r2]
				bx		lr

				ALIGN

				ENDP

				ENDIF

;///////////////////////////////////////////////////////////////////////////////

				ENDIF

				END
